package cn.software.service.impl;

import cn.software.entity.*;
import cn.software.entity.Class;
import cn.software.entity.param.*;
import cn.software.entity.vo.*;
import cn.software.mapper.*;
import cn.software.service.TestService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private TestMapper testMapper;
    @Autowired
    private StuTestMapper stuTestMapper;
    @Autowired
    private UserClassMapper userClassMapper;
    @Autowired
    private PaperMapper paperMapper;
    @Autowired
    private SubjectMapper subjectMapper;
    @Autowired
    private ClassMapper classMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TopicPaperMapper topicPaperMapper;
    @Autowired
    private TopicMapper topicMapper;
    @Autowired
    private StuTestRecordMapper stuTestRecordMapper;



    @Override
    public int addTest(TestParam testParam) {

        //开始时间早于当前时间不可添加考试
        Date date = new Date();
        if(testParam.getStartTime().before(date)){
            return -2;
        }

        int flag = 0;
        int timeConflict = isTimeConflict(testParam,flag);

        Test test = transformTestParamToTest(testParam);
        testMapper.insert(test);

        LambdaQueryWrapper<UserClass> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserClass::getClassId,testParam.getClassId());
        List<UserClass> listUserClass = userClassMapper.selectList(queryWrapper);

        for(UserClass userClass : listUserClass){
            StuTest stuTest = new StuTest();
            stuTest.setUserId(userClass.getUserId());
            stuTest.setTestId(test.getId());
            stuTest.setStatus(0);
            stuTest.setScore(0);

            stuTestMapper.insert(stuTest);
        }

        return timeConflict;
    }

    @Override
    public List<StuTestVo> getTestInfById(Integer id) {
        List<StuTestVo> listStuTestVo = new ArrayList<>();

        //根据考试id获取stu_test列表
        LambdaQueryWrapper<StuTest> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StuTest::getTestId,id);
        List<StuTest> listStuTest = stuTestMapper.selectList(queryWrapper);

        //将stuTest拷贝给stuTestVo列表
        for(StuTest stuTest : listStuTest){
            StuTestVo stuTestVo = transformStuTestToTSteTestVo(stuTest);
            //根据userId获取userName
            User user = userMapper.selectById(stuTest.getUserId());
            stuTestVo.setUserName(user.getName());

            listStuTestVo.add(stuTestVo);
        }

        return listStuTestVo;
    }

    @Override
    public TestVo getTestById(Integer id) {
        Test test = testMapper.selectById(id);
        TestVo testVo = transformTestToTestVo(test);
        return testVo;
    }

    private StuTestVo transformStuTestToTSteTestVo(StuTest stuTest) {
        StuTestVo stuTestVo = new StuTestVo();
        BeanUtils.copyProperties(stuTest,stuTestVo);
        return stuTestVo;
    }


    @Override
    public List<TestVo> getAllTest() {
        LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Test::getIsDeleted,0);

        List<Test> listTest = testMapper.selectList(queryWrapper);
        List<TestVo> listTestVo = new ArrayList<>();
        for(Test test:listTest){
            TestVo testVo = transformTestToTestVo(test);
            listTestVo.add(testVo);
        }
        return listTestVo;
    }

    @Override
    public int deleteTestById(Integer id) {
        Test test = testMapper.selectById(id);
        TestParam testParam = transformTestToTestParam(test);
        int flag = isTestBeginOrEnd(testParam);
        if( flag < 0){
            return flag;
        }
        test.setIsDeleted(1);
        int insert = testMapper.updateById(test);
        return insert;
    }

    private TestParam transformTestToTestParam(Test test) {
        TestParam testParam = new TestParam();
        BeanUtils.copyProperties(test,testParam);
        return testParam;
    }

    @Override
    public int updateTest(TestParam testParam) {
        int flag = 1;
        int timeConflict = isTimeConflict(testParam,flag);
        Test test = transformTestParamToTest(testParam);
        testMapper.updateById(test);

        return timeConflict;
    }

    /**
     * 判断参加考试时间是否冲突
     * 参加考试时间早于考试开始时间 return 1
     * 参加考试时间晚于考试结束时间 return 2
     * 正常参加 return 3
     * @param takeTestParam
     * @return
     */
    @Override
    public int isConflictTestTime(TakeTestParam takeTestParam) {
        Date date = new Date();

        Test test = testMapper.selectById(takeTestParam.getTestId());
        if(test.getStartTime().after(date)){
            return 1;
        }else if(test.getEndTime().before(date)){
            return 2;
        }else{
            return 3;
        }
    }

    @Override
    public PaperVo takeTest(TakeTestParam takeTestParam) {

        //根据testId查询到考试信息
        Test test = testMapper.selectById(takeTestParam.getTestId());



        //根据考试信息中paperId查询到试卷信息
        Paper paper = paperMapper.selectById(test.getPaperId());

        PaperVo paperVo = transformPaperToPaperVo(paper);

        //查询topic_paper表获取题目id列表
        LambdaQueryWrapper<TopicPaper> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TopicPaper::getPaperId,paper.getId());
        List<TopicPaper> listTopicPaper = topicPaperMapper.selectList(queryWrapper);

        //根据题目id查询题目信息，并添加到topicVo列表中
        List<TopicVo> topicVos = new ArrayList<>();
        for(TopicPaper topicPaper:listTopicPaper){
            Topic topic = topicMapper.selectById(topicPaper.getTopicId());
            TopicVo topicVo = transformTopicToTopicVo(topic);
            topicVos.add(topicVo);
        }
        //将topicVo列表信息写如paperVo中
        paperVo.setTopicVos(topicVos);
        return paperVo;
    }

    private TopicVo transformTopicToTopicVo(Topic topic) {
        TopicVo topicVo = new TopicVo();
        BeanUtils.copyProperties(topic,topicVo);

        Subject subject = subjectMapper.selectById(topic.getSubjectId());
        SubjectVo subjectVo = transformSubjectToSubjectVo(subject);
        topicVo.setSubjectVo(subjectVo);
        return topicVo;
    }

    private SubjectVo transformSubjectToSubjectVo(Subject subject) {
        SubjectVo subjectVo = new SubjectVo();
        BeanUtils.copyProperties(subject,subjectVo);
        return subjectVo;
    }

    private PaperVo transformPaperToPaperVo(Paper paper) {
        PaperVo paperVo = new PaperVo();
        BeanUtils.copyProperties(paper,paperVo);
        return paperVo;
    }

    /**
     * 判断考试是否开始或结束
     * 返回-3 考试正在进行
     * 返回-4 考试已经结束
     * 返回1 考试未开始
     */
    public int isTestBeginOrEnd(TestParam testParam){
        Date date = new Date();
        if(testParam.getStartTime().before(date)){
            return -3;
        }
        if(testParam.getEndTime().before(date)){
            return -4;
        }
        return 1;
    }

    /**
     * 判断考试是否重复
     * 重复返回true
     * 不重复返回false
     * @param testParam
     * @return
     */

    public boolean isTestRepetition(TestParam testParam){
        LambdaQueryWrapper<Test> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Test::getIsDeleted,0);
        List<Test> listTest = testMapper.selectList(queryWrapper);
        System.out.println(testParam);
        for (Test test : listTest){
            System.out.println(test);
            if(test.getPaperId() == testParam.getPaperId()
            && test.getStartTime() == testParam.getStartTime()){
                return true;
            }
        }
        return false;
    }


    /**
     * 判断新增考试或者修改考试时 是否与原有考试时间存在冲突
     * 不存在冲突：返回 -1
     * 存在冲突： 返回 冲突考试id
     * @param testParam
     * @return
     */
    public int isTimeConflict(TestParam testParam,int flag){
        //根据考试classId查询user_class表
        LambdaQueryWrapper<UserClass> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserClass::getClassId,testParam.getClassId());
        List<UserClass> listUserClass = userClassMapper.selectList(queryWrapper);
        if(!listUserClass.isEmpty()){
            int userId = listUserClass.get(0).getUserId();

            //根据UserId查询test表 获取test
            LambdaQueryWrapper<StuTest> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(StuTest::getUserId,userId);
            List<StuTest> listStuTest = stuTestMapper.selectList(queryWrapper1);

            //根据test_id查询test表
            for (StuTest stuTest : listStuTest) {
                Test test = testMapper.selectById(stuTest.getId());
                if(flag == 1 && test.getId() == testParam.getId()){}
                //时间冲突
                else if(test.getIsDeleted()==0 && (test.getStartTime().before(testParam.getEndTime())
                        || test.getEndTime().after(testParam.getStartTime())
                        || test.getStartTime().equals(testParam.getStartTime()))){
                    //返回冲突考试id
                    return test.getId();
                }
            }
        }
        return -1;
    }

    /**
     * 用于所有 考试查询接口
     * 将test中值拷贝到testVo中testVo中添加查询到的paperName、subjectName、className添加到testVo中
     * @param test
     * @return
     */
    public TestVo transformTestToTestVo(Test test){
        TestVo testVo = new TestVo();
        BeanUtils.copyProperties(test,testVo);

        //将查到的paperName赋值给testVo
        Paper paper = paperMapper.selectById(test.getPaperId());
        testVo.setPaperName(paper.getName());
        //将查到的subjectName赋值给testVo
        Subject subject = subjectMapper.selectById(paper.getSubjectId());
        testVo.setSubjectName(subject.getName());
        //将查到的className赋值给testVo
        LambdaQueryWrapper<Class> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Class::getSubjectId,subject.getId());
        List<Class> listclass = classMapper.selectList(queryWrapper1);
        testVo.setClassName(listclass.get(0).getName());

        return testVo;
    }


    public Test transformTestParamToTest(TestParam testParam){
        Test test = new Test();
        BeanUtils.copyProperties(testParam,test);
        return test;
    }

    @Override
    public boolean submitTestPaper(StuTestRecordParam stuTestRecordParam) {
        int insert=0,totalScore=0;
        StuTestRecord stuTestRecord = new StuTestRecord();

        StuTest stuTest = stuTestMapper.selectById(stuTestRecordParam.getStuTestId());

        for(TopicAnswerParam topicAnswerParam : stuTestRecordParam.getTopicAnswer()){
            stuTestRecord.setStuTestId(stuTestRecordParam.getStuTestId());
            stuTestRecord.setTopicId(topicAnswerParam.getTopicId());
            stuTestRecord.setAnswer(topicAnswerParam.getAnswer());

            Topic topic = topicMapper.selectById(topicAnswerParam.getTopicId());
            if(topic.getType() == 1 || topic.getType() == 2 || topic.getType() == 4){
                if(topic.getAnswer().equals(topicAnswerParam.getAnswer())){
                    stuTestRecord.setScore(topic.getScore());
                    //将正确的题目的分数加到试卷总分中
                    stuTest.setScore(stuTest.getScore() + topic.getScore());
                }else{
                    stuTestRecord.setScore(0);
                }
                //简答题分值暂时赋值为0，老师手动批改分数
            }else{
                stuTestRecord.setScore(0);
            }
            insert += stuTestRecordMapper.insert(stuTestRecord);
        }
        stuTestMapper.updateById(stuTest);
        return insert >0 ;
    }

    @Override
    public boolean teacherCorrectsPaper(TeacherCorrectPaperParam teacherCorrectPaperParam) {
        StuTest stuTest = stuTestMapper.selectById(teacherCorrectPaperParam.getStuTestId());

        for(TeacherCorrectTestParam teacherCorrectTestParam : teacherCorrectPaperParam.getTopicAnswers()){
            //将老师批改的答案存入stu_test_record表中
            StuTestRecord stuTestRecord = stuTestRecordMapper.selectById(teacherCorrectTestParam.getTopicId());
            stuTestRecord.setScore(teacherCorrectTestParam.getScore());
            stuTestRecordMapper.updateById(stuTestRecord);
            //将分数加入该试卷总分中
            stuTest.setScore(stuTest.getScore() + stuTestRecord.getScore());
        }
        stuTestMapper.updateById(stuTest);
        return true;
    }

    @Override
    public List<TopicAnswerVo> getSAQ(Integer stuTestId) {
        List<TopicAnswerVo> listTopicAnswerVo = new ArrayList<>();

        LambdaQueryWrapper<StuTestRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StuTestRecord::getStuTestId,stuTestId);
        List<StuTestRecord> listStuTestRecord = stuTestRecordMapper.selectList(queryWrapper);

        for(StuTestRecord stuTestRecord : listStuTestRecord){
            Topic topic = topicMapper.selectById(stuTestRecord.getTopicId());
            TopicAnswerVo topicAnswerVo = transformTopicToTopicAnswerVo(topic);
            topicAnswerVo.setAnswer(stuTestRecord.getAnswer());

            listTopicAnswerVo.add(topicAnswerVo);
        }
        return listTopicAnswerVo;
    }

    private TopicAnswerVo transformTopicToTopicAnswerVo(Topic topic) {
        TopicAnswerVo topicAnswerVo = new TopicAnswerVo();
        BeanUtils.copyProperties(topic,topicAnswerVo);
        return topicAnswerVo;
    }

    @Override
    public TreeVo getTree(Integer teacherId) {
        Date date = new Date();

        List<TestVo> listTestVo = getTestVoByTeacherId(teacherId);

        List<TestVo> testVoEnded = new ArrayList<>();
        List<TestVo> testVoTesting = new ArrayList<>();
        List<TestVo> testVoNotStart = new ArrayList<>();

        for(TestVo testVo:listTestVo){
            if(testVo.getStartTime().after(date)){
                testVoNotStart.add(testVo);
            }else if(testVo.getStartTime().before(date) && testVo.getEndTime().after(date)){
                testVoTesting.add(testVo);
            }else if(testVo.getEndTime().before(date)){
                testVoEnded.add(testVo);
            }
        }

        TreeVo treeVo = new TreeVo(testVoNotStart,testVoTesting,testVoEnded);
        return treeVo;
    }

    @Override
    public TimeVo getTime(Integer teacherId) {
        List<TestVo> listTestVo = getTestVoByTeacherId(teacherId);

        TimeVo timeVo = new TimeVo(listTestVo);

        return timeVo;
    }

    /**
     * 获取老师对应的考试
     */
    public List<TestVo> getTestVoByTeacherId(Integer teacherId){
        List<TestVo> listTestVo = new ArrayList<>();
        LambdaQueryWrapper<Class> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Class::getTeacherId,teacherId);
        List<Class> listClass = classMapper.selectList(queryWrapper);

        for(Class cls : listClass){
            LambdaQueryWrapper<UserClass> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(UserClass::getClassId,cls.getId());
            UserClass userClass = userClassMapper.selectOne(queryWrapper1);

            if(userClass!=null){
                LambdaQueryWrapper<StuTest> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(StuTest::getUserId,userClass.getUserId());
                List<StuTest> listStuTest = stuTestMapper.selectList(queryWrapper2);

                for(StuTest stuTest : listStuTest){
                    Test test = testMapper.selectById(stuTest.getTestId());
                    TestVo testVo = transformTestToTestVo(test);
                    listTestVo.add(testVo);
                }
            }
        }
        return listTestVo;
    }
}
